#pragma once
#include "Task.hpp"
#include <iostream>
#include <vector>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>

const int gdefault_nums = 5;

// 先描述 定义管道(父进程需对每个管道写端进行维护)
class Channel
{
public:
    Channel(int wfd, pid_t subid)
        : _wfd(wfd), _subid(subid)

    {
        // 对name初始化
        _name = "channel->" + std::to_string(_wfd) + "-> " + std::to_string(_subid);
    }

    // 管道信息
    int Fd() { return _wfd; }
    int Id() { return _subid; }
    std::string Name() { return _name; }

    // 发送任务
    void Send(int task_code)
    {

        write(_wfd, &task_code, sizeof(task_code));
    }

    // 子进程停止
    void Stop()
    {
        close(_wfd);
    }

    // 子进程回收
    void Wait()
    {
        waitpid(_subid, nullptr, 0);
    }
    ~Channel() {}

private:
    int _wfd;
    int _subid;
    std::string _name;
};

// 再组织 利用vector管理管道
class Channel_Manger
{
public:
    Channel_Manger() : _next(0)
    {
    }

    void BuildChannel(int wfd, pid_t subid)
    {

        // 构建Channel对象 将管道插入vector管理
        Channel c = Channel(wfd, subid);
        _channels.push_back(c);
    }

    // 信道选择
    Channel &Select()
    {
        Channel &tmp = _channels[_next];
        _next++;
        // 对_next做边界处理
        _next %= _channels.size();
        return tmp;
    }

    void PrintChannel()
    {
        for (int i = 0; i < gdefault_nums; i++)
            // 打印管道信息
            std::cout << _channels[i].Name() << std::endl;
    }

    void CloseAll()
    {
        for (auto &channel : _channels)
        {
            channel.Stop();
        }
    }

    // 停止并回收所有子进程
    void StopAndWait()
    {

        for (auto &channel : _channels)
        {
            // 1. 子进程停止 ---关闭所有管道的写端
            channel.Stop();
            std::cout << "关闭： " << channel.Name() << std::endl;
            // 2. 子进程回收
            channel.Wait();
            std::cout << "回收： " << channel.Name() << std::endl;
        }
    }
    ~Channel_Manger() {}

private:
    std::vector<Channel> _channels;
    int _next;
};

// 定义进程池
class Process_Pool
{
public:
    Process_Pool(int nums)
        : _process_nums(nums)
    {
        // 初始化方法
        _task.Task_Register(task1);
        _task.Task_Register(task2);
        _task.Task_Register(task3);
        _task.Task_Register(task4);
    }

    bool Creat()
    {
        for (int i = 0; i < _process_nums; i++)
        {
            // 创建管道
            int pipefd[2];
            int ret = pipe(pipefd);
            if (ret < 0)
            {
                return false;
            }

            // 创建子进程
            pid_t subid = fork();
            if (subid < 0)
                return false;

            else if (subid == 0)
            {

                // child-> r
                // 去掉子进程写端口
                close(pipefd[1]);
                // 关闭继承父进程以来的所有写端的文件描述符
                _cm.CloseAll();
                // 子进程进行读工作
                Work(pipefd[0]);

                // 子进程退出
                exit(0);
            }

            else
            {
                // father-> w
                close(pipefd[0]);
                // 调用Channel_Manger管理函数进行管道管理
                _cm.BuildChannel(pipefd[1], subid);
            }
        }
        return true;
    }

    // 任务发布接口
    void Run()
    {
        // 1. 确定代码
        int task_code = _task.Code();

        // 2. 选择信道 负载均衡选择一个信道(轮询方式)
        auto &c = _cm.Select();
        std::cout << "选择了一个子进程: " << c.Name() << std::endl;

        // 3. 发送任务
        c.Send(task_code);
        std::cout << "发送了一个任务码: " << task_code << std::endl;
    }
    // 子进程工作
    void Work(int rfd)
    {
        int code = 0;
        while (true)
        {

            code = 0;
            // 子进程进行任务码读取
            ssize_t len = read(rfd, &code, sizeof(code));
            if (len < 0)
            {
                std::cout << "读取失败" << std::endl;
                break;
            }

            else if (len == 0)
            { // 写端关闭
                std::cout << "子进程退出" << std::endl;
                break;
            }

            else
            { // 读取成功
                if (len != sizeof(code))
                {
                    continue;
                }

                else
                {
                    // 执行任务
                    _task.Execute(code);
                }
            }
        }
    }

    // Debug
    void Debug()
    {
        _cm.PrintChannel();
    }

    // 停止所有子进程
    void Stop()
    {
        _cm.StopAndWait();
    }
    ~Process_Pool() {}

private:
    int _process_nums;
    Channel_Manger _cm;
    Task_Manger _task;
};